package com.zjxny.jobs;

import java.util.Date;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import javax.annotation.Resource;

import org.dromara.sms4j.api.entity.SmsResponse;
import org.dromara.sms4j.core.factory.SmsFactory;
import org.dromara.sms4j.provider.enumerate.SupplierType;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import com.zjxny.vo.SmsSendCfg;
import com.zjxny.vo.SmsSendResponse;
import com.zjxny.vo.SmsTrafficSimpleVO;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import xyz.erupt.core.annotation.EruptHandlerNaming;
import xyz.erupt.job.handler.EruptJobHandler;

@Service
@Slf4j
@EruptHandlerNaming("发送短信服务")
public class SendSmsJob implements EruptJobHandler {
	private final Lock lock = new ReentrantLock();
    private boolean shouldSkip = false;
    
    @Value("${traffic.smsSleep.min:500}")
	Long sleepTimeMin;
    
    @Value("${traffic.smsSleep.max:3000}")
	Long sleepTimeMax;
    
	@Resource
	JdbcTemplate jdbcTemplate;

	@Override
	public String exec(String code, String param) {
		log.info("SendSmsJob.exec ...");
		
		lock.lock();
		try {
			if (shouldSkip) {
				log.warn("Skipping SendSmsJob.task...");
				return null;
			}

			shouldSkip = true;			
			Integer limit = 100;
			if(StrUtil.isNotBlank(param)) {
				limit = Integer.valueOf(param);
			}
			//查询出来待发送的短信
			String sql = "select * from sms_info where customer_info_id is not null and status=0 limit "+limit;
			List<Map<String,Object>> list = jdbcTemplate.queryForList(sql);
			if(list.isEmpty()) {
				return "暂无短信可发";
			}
			
			Iterator<Map<String,Object>> iter =  list.iterator();
			while(iter.hasNext()) {
				Map<String,Object> data = iter.next();
				Long id = (Long) data.get("id");
				String hphm = (String) data.get("hphm");
				Long cusId = 0L;
				if(ObjectUtil.isNull(data.get("customer_info_id"))) {
					log.info("smsinfo.id={} has not customer id",id);
					continue;
				}
				
				SmsSendCfg smsSendCfg = new SmsSendCfg();
				smsSendCfg.setHphm(hphm);
				smsSendCfg.setSmsInfo(data);
				
				cusId = (Long) data.get("customer_info_id");
				
				Map<String,Object> userData = jdbcTemplate.queryForMap("select * from customer_info where id = "+cusId);
				String userName =(String) userData.get("user_name");
				String phoneNo = (String) userData.get("phone_no");
				
				smsSendCfg.setUserName(userName);
				smsSendCfg.setPhoneNo(phoneNo);
				
				Long smsTplId = (Long)data.get("sms_tpl_info_id");
				Map<String,Object> smsTplData = jdbcTemplate.queryForMap("select * from sms_tpl_info where id = "+smsTplId);
				String tplCode = (String) smsTplData.get("code");
				String tplName = (String) smsTplData.get("title");
				
				smsSendCfg.setSmsTplCode(tplCode);
				smsSendCfg.setSmsTplTitle(tplName);
				
				Integer smsType = (Integer) data.get("type"); 	
				
				SmsSendResponse smsSendResponse = null;
				switch (smsType) {
				case 1:
					smsSendResponse= sendTrafficFirst(smsSendCfg);
					break;
				case 2:
					smsSendResponse = sendTrafficTwo(smsSendCfg);
					break;
				case 3:
					smsSendResponse =sendTrafficThird(smsSendCfg);
					break;
				case 4:
					smsSendResponse = sendYearCheckFirst(smsSendCfg);
					break;
				case 5:
					smsSendResponse =sendYearCheckTwo(smsSendCfg);
					break;
				case 6:
					smsSendResponse = sendYearCheckThird(smsSendCfg);
					break;
				default:
					break;
				}
				
				String usql = "update sms_info set update_time=now(),status = 1,num=num+1,last_send_date='"+DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN)+"' where id="+id;
				int affectNum = jdbcTemplate.update(usql);
				log.info("update.sms.send.done. id={},hphm={},affectNum={},usql={},smsSendResponse={}",id,hphm,affectNum,usql,JSONUtil.toJsonPrettyStr(smsSendResponse));
				
				String smsContent = smsSendResponse.getSmsContent();
				Integer sendStauts = smsSendResponse.getSmsResponse().isSuccess()?1:-1;
				String errorMsg = "";
				if(!smsSendResponse.getSmsResponse().isSuccess()) {
					errorMsg = smsSendResponse.getSmsResponse().getCode()+"|"+smsSendResponse.getSmsResponse().getMessage();
				} else {
					errorMsg = smsSendResponse.getSmsResponse().getBizId();
				}
				String response=JSONUtil.toJsonStr(smsSendResponse);
				
				//写入发送短信记录
				String iSQLPrefix = "insert into sms_history(last_send_time,create_time,update_time,tpl_code,tpl_name,user_name,phone_no,hphm,content,status,error_msg,response) values(now(),now(),now()";
				String iSQL = iSQLPrefix+",?,?,?,?,?,?,?,?,?)";
				affectNum = jdbcTemplate.update(iSQL,tplCode,tplName,userName,phoneNo,hphm,smsContent,sendStauts,errorMsg,response);
				
				log.info("insert.sms.recored. id={},hphm={},affectNum={},iSQL={}",id,hphm,affectNum,iSQL);
			}
			
			shouldSkip = false;
		} finally {
			shouldSkip = false;
			lock.unlock();
		}
		return null;
	}
	
	/**
	 * 根据文书号查询违章基本信息
	 * @param xh
	 * @return
	 */
	private SmsTrafficSimpleVO getTrafficData(String xh){
		Map<String,Object> data =  jdbcTemplate.queryForMap("select * from traffic_info where xh='"+xh+"'");
		SmsTrafficSimpleVO rdata = new SmsTrafficSimpleVO();
		rdata.setHphm(Convert.toStr(data.get("hphm")));
		
		Date wfsj = Convert.toDate(data.get("wfsj"));
		rdata.setTime(DateUtil.format(wfsj, DatePattern.NORM_DATE_PATTERN));
		rdata.setContent(Convert.toStr(data.get("wfms")));
		rdata.setAddress(Convert.toStr(data.get("wfdz")));
		rdata.setMoney(Convert.toStr(data.get("fkje")));
		rdata.setScore(Convert.toStr(data.get("wfjfs")));
		
		return rdata;
	}
	
	//d0
	private SmsSendResponse sendTrafficFirst(SmsSendCfg smsSendCfg) {
		LinkedHashMap<String,String> params = new LinkedHashMap<String,String>();
		SmsTrafficSimpleVO traffic = getTrafficData(Convert.toStr(smsSendCfg.getSmsInfo().get("xh")));
        params.put("carno", smsSendCfg.getHphm());
        params.put("time", traffic.getTime());
        
        String address = traffic.getAddress().replaceAll("[（）()-+－、\t ]", "");
        params.put("address",address);
        params.put("content",traffic.getContent());
        params.put("score",traffic.getScore());
        params.put("money",traffic.getMoney());
        params.put("phoneno",smsSendCfg.getCustomerPhoneNo());
        
        String msgContent = traffic.getContent();
        String content = String.format("亲爱的用户,您的用车%s于%s在%s违法,违法内容:%s,扣%s分,罚款%s元,请务必于5日内处理清结,以免造成其他次生损失! 客服电话:%s", 
        		smsSendCfg.getHphm(),traffic.getTime(),address,msgContent,traffic.getScore(),traffic.getMoney(),smsSendCfg.getCustomerPhoneNo());
        SmsResponse response =  SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(smsSendCfg.getPhoneNo(),smsSendCfg.getSmsTplCode(),params);
        
        SmsSendResponse res = new SmsSendResponse();
        res.setSmsContent(content);
        res.setSmsResponse(response);
        return res;
	}

	//d3
	private SmsSendResponse sendTrafficTwo(SmsSendCfg smsSendCfg) {
		LinkedHashMap<String,String> params = new LinkedHashMap<String,String>();
		SmsTrafficSimpleVO traffic = getTrafficData(Convert.toStr(smsSendCfg.getSmsInfo().get("xh")));
        params.put("carno", smsSendCfg.getHphm());
        params.put("time", traffic.getTime());
        
        String address = traffic.getAddress().replaceAll("[（）()-+－、\t ]", "");
        params.put("address",address);
        
        params.put("content",traffic.getContent());
        params.put("score",traffic.getScore());
        params.put("money",traffic.getMoney());
        params.put("phoneno",smsSendCfg.getCustomerPhoneNo());
        
        String msgContent = traffic.getContent();
        String content = String.format("亲爱的用户,您的用车%s于${time}在%s违法,违法内容:%s,扣%s分,罚款%s元,还未处理清结,请您尽快处理! 以免触发违约条款,影响车辆正常使用! 客服电话:%s", 
        		smsSendCfg.getHphm(),traffic.getTime(),address,msgContent,traffic.getScore(),traffic.getMoney(),smsSendCfg.getCustomerPhoneNo());
        
        SmsResponse response =  SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(smsSendCfg.getPhoneNo(),smsSendCfg.getSmsTplCode(),params);
        
        SmsSendResponse res = new SmsSendResponse();
        res.setSmsContent(content);
        res.setSmsResponse(response);
        return res;
	}

	//d15
	private SmsSendResponse sendTrafficThird(SmsSendCfg smsSendCfg) {
		LinkedHashMap<String,String> params = new LinkedHashMap<String,String>();
		SmsTrafficSimpleVO traffic = getTrafficData(Convert.toStr(smsSendCfg.getSmsInfo().get("xh")));
        params.put("carno", smsSendCfg.getHphm());
        params.put("time", traffic.getTime());
        
        String address = traffic.getAddress().replaceAll("[（）()-+－、\t ]", "");
        params.put("address",address);
        
        params.put("content",traffic.getContent());
        params.put("score",traffic.getScore());
        params.put("money",traffic.getMoney());
        params.put("phoneno",smsSendCfg.getCustomerPhoneNo());
        
        String msgContent = traffic.getContent();
        String content = String.format("亲爱的用户,您的用车%s于${time}在%s违法,违法内容:%s,扣%s分,罚款%s元,尚未处理清洁,您的驾驶行为信息已同步交管信息平台,请务必及时处理清洁,以免造成其他损失及相关合约累! 客服电话:${phoneno}", 
        		smsSendCfg.getHphm(),traffic.getTime(),address,msgContent,traffic.getScore(),traffic.getMoney(),smsSendCfg.getCustomerPhoneNo());
        SmsResponse response =  SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(smsSendCfg.getPhoneNo(),smsSendCfg.getSmsTplCode(),params);
        
        SmsSendResponse res = new SmsSendResponse();
        res.setSmsContent(content);
        res.setSmsResponse(response);
        
        return res;
	}
	
	/**
	 * 获取年检时间
	 * @param hphm
	 * @return
	 */
	private String getCarCheckTime(String hphm) {
		String sql = "select yxqz from car_info where hphm='"+hphm+"' limit 0,1";
		log.info("getCarCheckTime.invoke sql={}",sql);
		return jdbcTemplate.queryForObject(sql, String.class);
	}
	
	//年检类D60
	private SmsSendResponse sendYearCheckFirst(SmsSendCfg smsSendCfg) {
		LinkedHashMap<String,String> params = new LinkedHashMap<String,String>();
		String time = getCarCheckTime(smsSendCfg.getHphm());
        params.put("carno", smsSendCfg.getHphm());
        params.put("time", time);
        params.put("phoneno",smsSendCfg.getCustomerPhoneNo());
        String content = String.format("亲爱的用户,您的用车%s检验有效期至%s,请按时办理车辆检审. 客服电话:%s",smsSendCfg.getHphm(),time,smsSendCfg.getCustomerPhoneNo());
        SmsResponse response =  SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(smsSendCfg.getPhoneNo(),smsSendCfg.getSmsTplCode(),params);
        SmsSendResponse res = new SmsSendResponse();
        res.setSmsContent(content);
        res.setSmsResponse(response);
        return res;
	}

	//D30
	private SmsSendResponse sendYearCheckTwo(SmsSendCfg smsSendCfg) {
		LinkedHashMap<String,String> params = new LinkedHashMap<String,String>();
		String time = getCarCheckTime(smsSendCfg.getHphm());
        params.put("carno", smsSendCfg.getHphm());
        params.put("time", time);
        params.put("phoneno",smsSendCfg.getCustomerPhoneNo());
        String content = String.format("亲爱的用户,您的用车%s检验有效期至%s,当前我司尚未收到检审完结回馈,我司将执行安全行驶行为规范约束,客服电话:%s",smsSendCfg.getHphm(),time,smsSendCfg.getCustomerPhoneNo());
        
        SmsResponse response =  SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(smsSendCfg.getPhoneNo(),smsSendCfg.getSmsTplCode(),params);
        SmsSendResponse res = new SmsSendResponse();
        res.setSmsContent(content);
        res.setSmsResponse(response);
        return res;
	}

	//d15
	private SmsSendResponse sendYearCheckThird(SmsSendCfg smsSendCfg) {
		LinkedHashMap<String,String> params = new LinkedHashMap<String,String>();
		String time = getCarCheckTime(smsSendCfg.getHphm());
        params.put("carno", smsSendCfg.getHphm());
        params.put("time", time);
        params.put("phoneno",smsSendCfg.getCustomerPhoneNo());
        String content = String.format("亲爱的用户,您的用车%s检验有效期至%s,当前我司尚未收到检审完结回馈,为行驶安全考虑,请立即停止上路行驶,待检车完结再恢复行驶,若由此造成的其他损害,我司将行驶追索的权利! 客服电话:%s", smsSendCfg.getHphm(),time,smsSendCfg.getCustomerPhoneNo());
        SmsResponse response =  SmsFactory.createSmsBlend(SupplierType.ALIBABA).sendMessage(smsSendCfg.getPhoneNo(),smsSendCfg.getSmsTplCode(),params);
        SmsSendResponse res = new SmsSendResponse();
        res.setSmsContent(content);
        res.setSmsResponse(response);
        return res;
	}
	
	public static void main(String[] args) {
		String msg = "亲爱的用户,您的用车粤BDJ9817于2023-12-20在珠三角环线高速（增莞高速公路）石滩收费站北K79+134路段（南往北）违法,违法内容:非紧急情况时在高速公路应急车道上行驶的,扣6分,罚款100元,请务必于5日内处理清结,以免造成其他次生损失! 客服电话:4000011290";
		System.err.println(msg.replaceAll("[（）()-+－、\t]", ""));
	}
}